package message.controller;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import message.Message;
import message.visitor.MessageVisitor;

/**
 * Controller over a stalker that handles messages
 */

public class MessageController<T> implements Runnable {
  
  private final static int QUEUE_SIZE = 50;
  private final BlockingQueue<Message> queue_;
  private final MessageVisitor<T> visitor_;
  
  /**
   * Constructs a controller that's responsible for its caller
   * @requires parameters not null
   * @param owner Stalker that spawned this.
   * @param visitor Visitor for the messages of this controller
   */
  public MessageController(MessageVisitor<T> visitor) {
    assert (visitor != null);
    visitor_ = visitor;
    queue_ = new ArrayBlockingQueue<Message>(QUEUE_SIZE);
  }
  
  /**
   * Adds an entry to the blocking queue
   * @requires message not null
   * @param message A message that's going to be queued
   */
  public void enqueueMessage(Message message) {
    assert message != null;
    queue_.add(message);
  }
  
  public void run() {
    while (true) {
      Message message = null;
      try {
        message = queue_.take();
      } catch (InterruptedException ie) {
        // finish all queues then qui
        while (!(queue_.isEmpty())) {
          try {
            message = queue_.take();
          } catch (InterruptedException ie2) {
            // interrupted twice, so we quit
            break;
          }
          message.accept(visitor_);
        }
        break;
      }
      message.accept(visitor_);
    }
    
  }
  
}
